package paidaxing.blog.file.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import paidaxing.blog.common.exception.BusinessException;
import paidaxing.blog.core.storage.MinioStorageService;
import paidaxing.blog.file.dto.FileDTO;
import paidaxing.blog.file.dto.response.FileResponseDTO;
import paidaxing.blog.file.entity.Files;
import paidaxing.blog.file.mapper.FileMapper;
import paidaxing.blog.file.service.FileService;

import jakarta.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FileServiceImpl implements FileService {
    
    @Resource
    private FileMapper fileMapper;
    
    @Resource
    private MinioStorageService minioStorageService;

    @Override
    public FileDTO uploadFile(MultipartFile file, String description) {
        try {
            // 生成唯一文件名
            String fileName = generateUniqueFileName(file.getOriginalFilename());
            
            // 上传到MinIO
            String fileUrl = minioStorageService.upload(file, fileName);
            
            // 保存文件信息到数据库
            Files files = new Files();
            files.setOriginalName(file.getOriginalFilename());
            files.setFileName(fileName);
            files.setFilePath(fileUrl);
            files.setFileSize(file.getSize());
            files.setFileType(getFileType(file.getOriginalFilename()));
            files.setMimeType(file.getContentType());
            files.setBucketName("blog-bucket");
            files.setUserId(StpUtil.getLoginIdAsLong());
            files.setIsImage(isImageFile(file.getContentType()) ? 1 : 0);
            files.setWidth(0);
            files.setHeight(0);
            files.setCreatedAt(new Date());
            files.setUpdatedAt(new Date());
            files.setDeleted(0);
            
            int result = fileMapper.insert(files);
            if (result <= 0) {
                throw new BusinessException("文件上传失败");
            }
            
            FileDTO fileDTO = new FileDTO();
            BeanUtils.copyProperties(files, fileDTO);
            return fileDTO;
        } catch (Exception e) {
            log.error("文件上传失败", e);
            throw new BusinessException("文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public FileDTO uploadImage(MultipartFile image, String description) {
        try {
            // 生成唯一文件名
            String fileName = generateUniqueFileName(image.getOriginalFilename());
            
            // 上传到MinIO
            String fileUrl = minioStorageService.upload(image, fileName);
            
            // 保存文件信息到数据库
            Files files = new Files();
            files.setOriginalName(image.getOriginalFilename());
            files.setFileName(fileName);
            files.setFilePath(fileUrl);
            files.setFileSize(image.getSize());
            files.setFileType(getFileType(image.getOriginalFilename()));
            files.setMimeType(image.getContentType());
            files.setBucketName("blog-bucket");
            files.setUserId(StpUtil.getLoginIdAsLong());
            files.setIsImage(1);
            files.setWidth(0);  // 实际项目中应该获取图片真实宽高
            files.setHeight(0); // 实际项目中应该获取图片真实宽高
            files.setCreatedAt(new Date());
            files.setUpdatedAt(new Date());
            files.setDeleted(0);
            
            int result = fileMapper.insert(files);
            if (result <= 0) {
                throw new BusinessException("图片上传失败");
            }
            
            FileDTO fileDTO = new FileDTO();
            BeanUtils.copyProperties(files, fileDTO);
            return fileDTO;
        } catch (Exception e) {
            log.error("图片上传失败", e);
            throw new BusinessException("图片上传失败: " + e.getMessage());
        }
    }

    @Override
    public FileResponseDTO getFileById(Long fileId) {
        Files files = fileMapper.queryById(fileId);
        if (files == null || files.getDeleted() == 1) {
            return null;
        }
        
        FileResponseDTO fileResponseDTO = new FileResponseDTO();
        BeanUtils.copyProperties(files, fileResponseDTO);
        return fileResponseDTO;
    }

    @Override
    public boolean deleteFile(Long fileId) {
        Files files = fileMapper.queryById(fileId);
        if (files == null || files.getDeleted() == 1) {
            return false;
        }
        
        // 检查权限：只能删除自己的文件
        Long currentUserId = StpUtil.getLoginIdAsLong();
        if (!files.getUserId().equals(currentUserId)) {
            throw new BusinessException("无权删除他人文件");
        }
        
        // 从MinIO删除文件
        try {
            minioStorageService.deleteFile(files.getFileName());
        } catch (Exception e) {
            log.warn("MinIO文件删除失败: {}", e.getMessage());
        }
        
        int result = fileMapper.deleteById(fileId);
        return result > 0;
    }

    @Override
    public List<FileResponseDTO> getFileList(Integer page, Integer size) {
        int offset = (page - 1) * size;
        List<Files> filesList = fileMapper.selectFilesByPage(offset, size);
        
        return filesList.stream().map(file -> {
            FileResponseDTO dto = new FileResponseDTO();
            BeanUtils.copyProperties(file, dto);
            return dto;
        }).collect(Collectors.toList());
    }

    @Override
    public byte[] downloadFile(Long fileId) {
        Files files = fileMapper.queryById(fileId);
        if (files == null || files.getDeleted() == 1) {
            throw new BusinessException("文件不存在");
        }
        
        try {
            // 从MinIO获取文件流
            InputStream inputStream = minioStorageService.getFileStream(files.getFileName());
            
            // 转换为字节数组
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int nRead;
            byte[] data = new byte[1024];
            while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, nRead);
            }
            buffer.flush();
            
            return buffer.toByteArray();
        } catch (Exception e) {
            log.error("文件下载失败", e);
            throw new BusinessException("文件下载失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成唯一文件名
     * @param originalFileName 原始文件名
     * @return 唯一文件名
     */
    private String generateUniqueFileName(String originalFileName) {
        String extension = "";
        if (originalFileName != null && originalFileName.contains(".")) {
            extension = originalFileName.substring(originalFileName.lastIndexOf("."));
        }
        return UUID.randomUUID().toString().replace("-", "") + extension;
    }
    
    /**
     * 根据文件名获取文件类型
     * @param fileName 文件名
     * @return 文件类型
     */
    private String getFileType(String fileName) {
        if (fileName == null) {
            return "unknown";
        }
        
        if (fileName.toLowerCase().endsWith(".jpg") || 
            fileName.toLowerCase().endsWith(".jpeg") || 
            fileName.toLowerCase().endsWith(".png") || 
            fileName.toLowerCase().endsWith(".gif")) {
            return "image";
        } else if (fileName.toLowerCase().endsWith(".pdf")) {
            return "pdf";
        } else if (fileName.toLowerCase().endsWith(".doc") || 
                   fileName.toLowerCase().endsWith(".docx")) {
            return "document";
        } else {
            return "other";
        }
    }
    
    /**
     * 判断是否为图片文件
     * @param contentType 文件MIME类型
     * @return 是否为图片
     */
    private boolean isImageFile(String contentType) {
        if (contentType == null) {
            return false;
        }
        return contentType.startsWith("image/");
    }
}